package com.huawei.deveco.common.security.util;

import java.nio.charset.StandardCharsets;
import java.security.InvalidParameterException;
import java.util.Locale;
import java.util.Objects;
import java.util.regex.Pattern;

public class ByteUtil {
    private static final char[] HEX_CHAR_TABLE = new char[]{
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            'A', 'B', 'C', 'D', 'E', 'F'};

    private static final String HEX_CHAR_STR = "0123456789ABCDEF";

    private static final String EMPTY_STR = "";

    private static final Pattern HEX_STR_PATTERN = Pattern.compile("^([0-9A-Fa-f]{2})+$");

    public static char[] bytes2chars(byte[] bytes) {
        Objects.requireNonNull(bytes, "bytes should not be null!");
        return (new String(bytes, StandardCharsets.UTF_8)).toCharArray();
    }

    public static boolean isHexBytes(String hexString) {
        if (hexString == null)
            return false;
        if (hexString.isEmpty())
            return true;
        return HEX_STR_PATTERN.matcher(hexString).matches();
    }

    public static byte[] hex2bytes(String hexString) {
        if (StringUtil.isEmpty(hexString))
            return new byte[0];
        if (!isHexBytes(hexString))
            throw new IllegalArgumentException("Illegal hex string!");
        String upperCaseHexString = hexString.toUpperCase(Locale.ENGLISH);
        char[] hexChars = upperCaseHexString.toCharArray();
        int length = upperCaseHexString.length() / 2;
        byte[] bytes = new byte[length];
        for (int i = 0; i < length; i++) {
            int pos = i * 2;
            bytes[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
        }
        return bytes;
    }

    public static String bytes2Hex(byte[] bytes) {
        if (bytes == null || bytes.length == 0)
            return "";
        StringBuilder hex = new StringBuilder(2 * bytes.length);
        for (byte by : bytes)
            hex.append(HEX_CHAR_TABLE[(by & 0xF0) >> 4]).append(HEX_CHAR_TABLE[by & 0xF]);
        return hex.toString();
    }

    private static byte charToByte(char ch) {
        int pos = "0123456789ABCDEF".indexOf(ch);
        if (pos == -1)
            throw new IllegalArgumentException("invalid char " + ch);
        return (byte) pos;
    }

    public static byte[] xor(byte[] bytes1, byte[] bytes2) {
        if (bytes1 == null || bytes2 == null)
            throw new InvalidParameterException("xor input should not be null!");
        if (bytes1.length != bytes2.length)
            throw new InvalidParameterException("size of xor input should be same!");
        byte[] bytes = new byte[bytes1.length];
        for (int i = 0; i < bytes1.length; i++)
            bytes[i] = (byte) (bytes1[i] ^ bytes2[i]);
        return bytes;
    }
}
